using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace Peepster
{
    public enum KeyModifiers
    {
        None = 0,
        Alt = 1,
        Control = 2,
        Shift = 4,
        Windows = 8
    }

    public class HotKey : IMessageFilter, IDisposable
    {
        private const int Id = 100;
        private const int WmHotkey = 0x0312;
        private IntPtr _handle;

        public HotKey(Keys key, KeyModifiers modifier, EventHandler hotKeyPressed)
        {
            HotKeyPressed = hotKeyPressed;
            RegisterHotKey(key, modifier);
            Application.AddMessageFilter(this);
        }

        public IntPtr Handle
        {
            get { return _handle; }
            set { _handle = value; }
        }

        #region IMessageFilter Members

        public bool PreFilterMessage(ref Message m)
        {
            switch (m.Msg)
            {
                case WmHotkey:
                    HotKeyPressed(this, new EventArgs());
                    return true;
            }
            return false;
        }

        #endregion

        [DllImport("user32.dll", SetLastError = true)]
        private static extern bool RegisterHotKey(IntPtr hWnd, int id, KeyModifiers fsModifiers, Keys vk);

        [DllImport("user32.dll", SetLastError = true)]
        private static extern bool UnregisterHotKey(IntPtr hWnd, int id);

        private event EventHandler HotKeyPressed;

        ~HotKey()
        {
            Application.RemoveMessageFilter(this);
            UnregisterHotKey(_handle, Id);
        }

        public void Dispose()
        {
            Application.RemoveMessageFilter(this);
            UnregisterHotKey(_handle, Id);
        }


        private void RegisterHotKey(Keys key, KeyModifiers modifier)
        {
            if (key == Keys.None)
                return;

            bool isKeyRegisterd = RegisterHotKey(_handle, Id, modifier, key);
            if (!isKeyRegisterd)
                throw new ApplicationException("Hotkey allready in use");
        }
    }
}